//package com.zws.cucumber.optimization.socket.connector;
//
//import com.github.tomakehurst.wiremock.WireMockServer;
//import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
//import com.github.tomakehurst.wiremock.core.WireMockApp;
//import com.github.tomakehurst.wiremock.jetty9.DefaultMultipartRequestConfigurer;
//import com.github.tomakehurst.wiremock.matching.RequestMatcherExtension;
//import com.github.tomakehurst.wiremock.servlet.WireMockHttpServletRequestAdapter;
//import com.github.tomakehurst.wiremock.stubbing.*;
//import com.github.tomakehurst.wiremock.verification.LoggedRequest;
//import com.github.tomakehurst.wiremock.verification.RequestJournal;
//import com.zws.cucumber.optimization.ZwsOptimizations;
//import com.zws.cucumber.optimization.socket.ZwsSockets;
//import com.zws.cucumber.util.ZwsMockUtil;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.util.ReflectionUtils;
//import wiremock.com.google.common.base.Predicate;
//import wiremock.org.eclipse.jetty.http.HttpParser;
//import wiremock.org.eclipse.jetty.io.Connection;
//import wiremock.org.eclipse.jetty.server.HttpChannelOverHttp;
//import wiremock.org.eclipse.jetty.server.HttpConnection;
//import wiremock.org.eclipse.jetty.server.LocalConnector;
//import wiremock.org.eclipse.jetty.server.Request;
//
//import java.io.IOException;
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.nio.ByteBuffer;
//import java.util.Map;
//import java.util.concurrent.TimeUnit;
//
//import static com.zws.cucumber.optimization.socket.oio.ZwsSocketFaultEnum.CONNECTION_RESET;
//import static com.zws.cucumber.optimization.socket.oio.ZwsSocketFaultEnum.READ_TIMEOUT;
//import static wiremock.com.google.common.collect.Iterables.find;
//
//public final class ZwsConnectorWiremockAdaptor implements ZwsConnectorAdaptor {
//
//    private static final Logger logger = LoggerFactory.getLogger(ZwsConnectorWiremockAdaptor.class);
//
//    private static final Method methodOfExecuteRequest;
//
//    static {
//        methodOfExecuteRequest = ReflectionUtils.findMethod(LocalConnector.class, "executeRequest", ByteBuffer.class);
//        methodOfExecuteRequest.setAccessible(true);
//    }
//
//    private LocalConnector localConnector;
//    private ZwsCallerExecutionWiremockConnector callerExecutionLocalConnector;
//
//    private final ZwsConnectorAdaptor func;
//    private final ZwsConnectorAdaptor executionInMainThreadFunc;
//
//    private final Runnable acceptorRunnable = () -> {
//        Thread thread = Thread.currentThread();
//        String name = thread.getName();
//        try {
//            thread.setName("main-wiremock");
//            callerExecutionLocalConnector.accept(0);
//        } catch (InterruptedException | IOException e) {
//            throw new RuntimeException(e);
//        } finally {
//            thread.setName(name);
//        }
//    };
//
//    private WireMockApp wireMockApp;
//    private RequestJournal requestJournal;
//    private StubMappings stubMappings;
//    private DefaultMultipartRequestConfigurer multipartRequestConfigurer = new DefaultMultipartRequestConfigurer();
//    private Map<String, RequestMatcherExtension> customMatchers;
//    private Scenarios scenarios;
//
//    public ZwsConnectorWiremockAdaptor(LocalConnector localConnector, WireMockServer wireMockServer) {
//        this.localConnector = localConnector;
//        this.func = localConnector::getResponse;
//        this.executionInMainThreadFunc = null;
//
//        setupWithWireMockServer(wireMockServer);
//    }
//
//    public ZwsConnectorWiremockAdaptor(LocalConnector localConnector, ZwsCallerExecutionWiremockConnector callerExecutionLocalConnector, WireMockServer wireMockServer) {
//        this.localConnector = localConnector;
//        this.func = localConnector::getResponse;
//
//        this.callerExecutionLocalConnector = callerExecutionLocalConnector;
//        this.executionInMainThreadFunc = (buf, head, time, unit) -> {
//            callerExecutionLocalConnector.setInvoking(true);
//            LocalConnector.LocalEndPoint endp = (LocalConnector.LocalEndPoint) ReflectionUtils.invokeMethod(methodOfExecuteRequest, callerExecutionLocalConnector, buf);
//            callerExecutionLocalConnector.getExecutor().execute(acceptorRunnable);
//            return endp.waitForResponse(head, time, unit);
//        };
//
//        setupWithWireMockServer(wireMockServer);
//    }
//
//    private void setupWithWireMockServer(WireMockServer wireMockServer) {
//        wireMockApp = getWireMockApp(wireMockServer);
//        requestJournal = getRequestJournal(wireMockApp);
//        stubMappings = getStubMappings(wireMockApp);
//        customMatchers = getCustomMatchers(stubMappings);
//        scenarios = getScenarios(stubMappings);
//    }
//
//    @Override
//    public Object getResponse(ByteBuffer requestBuffer, boolean head, long time, TimeUnit unit) throws Exception {
//        if (ZwsMockUtil.haveMockedTimeout()) {
//            LocalConnector localConnector = this.localConnector != null ? this.localConnector : this.callerExecutionLocalConnector;
//            LocalConnector.LocalEndPoint ep = localConnector.new LocalEndPoint();
//            ep.addInput(requestBuffer.duplicate());
//
//            Connection conn = localConnector.getDefaultConnectionFactory().newConnection(localConnector, ep);
//            ep.setConnection(conn);
//
//            HttpConnection httpConn = (HttpConnection) conn;
//
//            HttpParser httpParser = new HttpParser((HttpChannelOverHttp) (httpConn.getHttpChannel()));
//            ByteBuffer buf = requestBuffer.duplicate();
//            while (httpParser.getState() != HttpParser.State.END
//                    && httpParser.getState() != HttpParser.State.CLOSE
//                    && httpParser.getState() != HttpParser.State.CLOSED) {
//                httpParser.parseNext(buf);
//            }
//
//            Request req = httpConn.getHttpChannel().getRequest();
//            WireMockHttpServletRequestAdapter httpServletRequest = new WireMockHttpServletRequestAdapter(req, multipartRequestConfigurer, null, false);
//
//            long s = logger.isDebugEnabled() ? System.nanoTime() : 0;
//            StubMapping mapping = find(
//                    stubMappings.getAll(),
//                    getPredicate(httpServletRequest),
//                    StubMapping.NOT_CONFIGURED);
//            if (logger.isDebugEnabled()) {
//                logger.debug("Find stub mapping consuming {}ns", System.nanoTime() - s);
//            }
//
//            if (mapping != null
//                    && mapping.getResponse() != null
//                    && mapping.getResponse().getFixedDelayMilliseconds() != null
//                    && mapping.getResponse().getFixedDelayMilliseconds() > 0) {
//
//                scenarios.onStubServed(mapping);
//
//                requestJournal.requestReceived(
//                        ServeEvent.of(
//                                        LoggedRequest.createFrom(httpServletRequest),
//                                        ResponseDefinitionBuilder.okForEmptyJson().build(),
//                                        mapping)
//                                .complete(com.github.tomakehurst.wiremock.http.Response.notConfigured(), 0));
//
//                return READ_TIMEOUT;
//            }
//        }
//
//        ByteBuffer resp;
//        if (ZwsOptimizations.isJettyExecutionInMainThreadEnabled() && ZwsSockets.isMainThread()) {
//            resp = (ByteBuffer) executionInMainThreadFunc.getResponse(requestBuffer, head, time, unit);
//        } else {
//            resp = (ByteBuffer) func.getResponse(requestBuffer, head, time, unit);
//        }
//
//        if (resp != null) {
//            return resp;
//        } else {
//            return CONNECTION_RESET;
//        }
//    }
//
//    private WireMockApp getWireMockApp(WireMockServer wireMockServer) {
//        Field fieldOfWireMockApp = ReflectionUtils.findField(WireMockServer.class, "wireMockApp");
//        fieldOfWireMockApp.setAccessible(true);
//        return (WireMockApp) ReflectionUtils.getField(fieldOfWireMockApp, wireMockServer);
//    }
//
//    private StubMappings getStubMappings(WireMockApp wireMockApp) {
//        Field fieldOfStubMappings = ReflectionUtils.findField(WireMockApp.class, "stubMappings");
//        fieldOfStubMappings.setAccessible(true);
//        return (StubMappings) ReflectionUtils.getField(fieldOfStubMappings, wireMockApp);
//    }
//
//    private RequestJournal getRequestJournal(WireMockApp wireMockApp) {
//        Field fieldOfRequestJournal = ReflectionUtils.findField(WireMockApp.class, "requestJournal");
//        fieldOfRequestJournal.setAccessible(true);
//        return (RequestJournal) ReflectionUtils.getField(fieldOfRequestJournal, wireMockApp);
//    }
//
//    private Map<String, RequestMatcherExtension> getCustomMatchers(StubMappings stubMappings) {
//        Field fieldOfCustomMatchers = ReflectionUtils.findField(InMemoryStubMappings.class, "customMatchers");
//        fieldOfCustomMatchers.setAccessible(true);
//        return (Map<String, RequestMatcherExtension>) ReflectionUtils.getField(fieldOfCustomMatchers, stubMappings);
//    }
//
//    private Scenarios getScenarios(StubMappings stubMappings) {
//        Field fieldOfScenarios = ReflectionUtils.findField(InMemoryStubMappings.class, "scenarios");
//        fieldOfScenarios.setAccessible(true);
//        return (Scenarios) ReflectionUtils.getField(fieldOfScenarios, stubMappings);
//    }
//
//
//    private Predicate<StubMapping> getPredicate(com.github.tomakehurst.wiremock.http.Request request) {
//        return new Predicate<>() {
//            public boolean apply(StubMapping mapping) {
//                return mapping.getRequest().match(request, customMatchers).isExactMatch() &&
//                        (mapping.isIndependentOfScenarioState() || scenarios.mappingMatchesScenarioState(mapping));
//            }
//        };
//    }
//
//}
